/***********************************************************************
 *
 * $CVSHeader$
 *
 * This file is part of WebScarab, an Open Web Application Security
 * Project utility. For details, please see http://www.owasp.org/
 *
 * Copyright (c) 2002 - 2004 Rogan Dawes
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Getting Source
 * ==============
 *
 * Source for this application is maintained at Sourceforge.net, a
 * repository for free software projects.
 *
 * For details, please see http://www.sourceforge.net/projects/owasp
 *
 */

/*
 * ManualRequestPanel.java
 *
 * Created on September 15, 2003, 11:16 AM
 */

package org.owasp.webscarab.plugin.manualrequest.swing;

import java.net.MalformedURLException;
import java.text.ParseException;
import org.owasp.webscarab.model.Request;
import org.owasp.webscarab.model.Response;
import org.owasp.webscarab.model.ConversationID;

import org.owasp.webscarab.plugin.manualrequest.ManualRequest;
import org.owasp.webscarab.plugin.manualrequest.ManualRequestModel;
import org.owasp.webscarab.plugin.manualrequest.ManualRequestUI;

import org.owasp.webscarab.ui.swing.SwingPluginUI;
import org.owasp.webscarab.ui.swing.ConversationListModel;
import org.owasp.webscarab.ui.swing.ConversationRenderer;
import org.owasp.webscarab.ui.swing.RequestPanel;
import org.owasp.webscarab.ui.swing.ResponsePanel;

import org.owasp.webscarab.util.swing.ListComboBoxModel;
import org.owasp.webscarab.util.swing.SwingWorker;
import org.owasp.webscarab.util.swing.ColumnDataModel;

import javax.swing.border.TitledBorder;
import javax.swing.SwingUtilities;

import javax.swing.JOptionPane;
import javax.swing.ComboBoxModel;
import javax.swing.ListModel;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import java.util.logging.Logger;

/**
 *
 * @author  rdawes
 */
public class ManualRequestPanel extends javax.swing.JPanel implements SwingPluginUI, ManualRequestUI {
    
    /**
	 * 
	 */
	private static final long serialVersionUID = 277808739447506130L;
	private ManualRequestModel _model;
    private ManualRequest _manualRequest;
    
    private final RequestPanel _requestPanel;
    private final ResponsePanel _responsePanel;
    private final RequestUpdater _reqUpdater = new RequestUpdater();
    private final ResponseUpdater _respUpdater = new ResponseUpdater();
    
    private Logger _logger = Logger.getLogger(this.getClass().getName());
    
    /** Creates new form ManualRequestPanel */
    public ManualRequestPanel(ManualRequest manualRequest) {
        initComponents();
        
        _manualRequest = manualRequest;
        _model = _manualRequest.getModel();
        
        Request request = new Request();
        request.setMethod("GET");
        request.setVersion("HTTP/1.0");
        _requestPanel = new RequestPanel();
        _requestPanel.setEditable(true);
        _requestPanel.setRequest(request);
        _requestPanel.setBorder(new TitledBorder("Request"));
        conversationSplitPane.setLeftComponent(_requestPanel);
        
        _responsePanel = new ResponsePanel();
        _responsePanel.setEditable(false);
        _responsePanel.setResponse(null);
        _responsePanel.setBorder(new TitledBorder("Response"));
        conversationSplitPane.setRightComponent(_responsePanel);
        
        ListModel conversationList = new ConversationListModel(_model.getConversationModel());
        ComboBoxModel requestModel = new ListComboBoxModel(conversationList);
        requestComboBox.setModel(requestModel);
        requestComboBox.setRenderer(new ConversationRenderer(_model.getConversationModel()));
        
        requestComboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                requestComboBoxActionPerformed(e);
            }
        });
        
        _manualRequest.setUI(this);
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {//GEN-BEGIN:initComponents

        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        requestComboBox = new javax.swing.JComboBox();
        conversationSplitPane = new javax.swing.JSplitPane();
        jPanel2 = new javax.swing.JPanel();
        getCookieButton = new javax.swing.JButton();
        fetchResponseButton = new javax.swing.JButton();
        updateCookiesButton = new javax.swing.JButton();

        setLayout(new java.awt.BorderLayout());

        jPanel1.setLayout(new java.awt.BorderLayout());

        jLabel1.setText("Previous Requests : ");
        jLabel1.setMinimumSize(new java.awt.Dimension(135, 15));
        jPanel1.add(jLabel1, java.awt.BorderLayout.WEST);

        jPanel1.add(requestComboBox, java.awt.BorderLayout.CENTER);

        add(jPanel1, java.awt.BorderLayout.NORTH);

        conversationSplitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        conversationSplitPane.setResizeWeight(0.5);
        conversationSplitPane.setOneTouchExpandable(true);
        add(conversationSplitPane, java.awt.BorderLayout.CENTER);

        jPanel2.setLayout(new java.awt.GridLayout());

        getCookieButton.setText("Get Cookies");
        getCookieButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                getCookieButtonActionPerformed(evt);
            }
        });

        jPanel2.add(getCookieButton);

        fetchResponseButton.setText("Fetch Response");
        fetchResponseButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                fetchResponseButtonActionPerformed(evt);
            }
        });

        jPanel2.add(fetchResponseButton);

        updateCookiesButton.setText("Update CookieJar");
        updateCookiesButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                updateCookiesButtonActionPerformed(evt);
            }
        });

        jPanel2.add(updateCookiesButton);

        add(jPanel2, java.awt.BorderLayout.SOUTH);

    }//GEN-END:initComponents
    
    private void requestComboBoxActionPerformed(java.awt.event.ActionEvent evt) {
        Object o = requestComboBox.getSelectedItem();
        if (o instanceof ConversationID) {
            ConversationID id = (ConversationID) o;
            Request request = _model.getConversationModel().getRequest(id);
            _manualRequest.setRequest(request);
        }
    }
    
    private void updateCookiesButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateCookiesButtonActionPerformed
        _manualRequest.updateCookies();
    }//GEN-LAST:event_updateCookiesButtonActionPerformed
    
    private void getCookieButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_getCookieButtonActionPerformed
        try {
            Request request = _requestPanel.getRequest();
            if (request != null && request.getURL() != null) {
                _manualRequest.setRequest(request);
                _manualRequest.addRequestCookies();
            }
        } catch (MalformedURLException mue) {
            JOptionPane.showMessageDialog(this, new String[] {"The URL requested is malformed", mue.getMessage()}, "Malformed URL", JOptionPane.ERROR_MESSAGE);
        } catch (ParseException pe) {
            JOptionPane.showMessageDialog(this, new String[] {"The request is malformed", pe.getMessage()}, "Malformed Request", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_getCookieButtonActionPerformed
    
    private void fetchResponseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fetchResponseButtonActionPerformed
        try {
            Request request = _requestPanel.getRequest();
            fetchResponse(request);
        } catch (MalformedURLException mue) {
            JOptionPane.showMessageDialog(this, new String[] {"The URL requested is malformed", mue.getMessage()}, "Malformed URL", JOptionPane.ERROR_MESSAGE);
        } catch (ParseException pe) {
            JOptionPane.showMessageDialog(this, new String[] {"The request is malformed", pe.getMessage()}, "Malformed Request", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_fetchResponseButtonActionPerformed
    
    private void fetchResponse(final Request request) {
        if (request != null) {
            _requestPanel.setEnabled(false);
            fetchResponseButton.setEnabled(false);
            updateCookiesButton.setEnabled(false);
            getCookieButton.setEnabled(false);
            _manualRequest.setRequest(request);
            new SwingWorker() {
                public Object construct() {
                    try {
                        _manualRequest.fetchResponse();
                        return null;
                    } catch (Exception e) {
                        return e;
                    }
                }
                
                //Runs on the event-dispatching thread.
                public void finished() {
                    Object obj = getValue();
                    if (obj != null) {
                        Exception e = (Exception) obj;
                        JOptionPane.showMessageDialog(null, new String[] {"Error fetching response: ", e.toString()}, "Error", JOptionPane.ERROR_MESSAGE);
                        _logger.severe("Exception fetching response: " + e);
                        e.printStackTrace();
                    }
                    fetchResponseButton.setEnabled(true);
                    updateCookiesButton.setEnabled(true);
                    getCookieButton.setEnabled(true);
                    _requestPanel.setEnabled(true);
                }
            }.start();
        } else {
            _logger.severe("Can't fetch a null request");
        }
    }
    public javax.swing.JPanel getPanel() {
        return this;
    }
    
    public String getPluginName() {
        return new String("Manual Request");
    }
    
    public javax.swing.Action[] getConversationActions() {
        // could return two actions here: "load request in editor", and "replay request"
        return null;
    }
    
    public javax.swing.Action[] getUrlActions() {
        // doesn't really make sense at an URL level
        return null;
    }
    
    public void requestChanged(Request request) {
        _reqUpdater.setRequest(request);
    }
    
    public void responseChanged(Response response) {
        _respUpdater.setResponse(response);
    }
    
    public void setEnabled(final boolean enabled) {
        if (SwingUtilities.isEventDispatchThread()) {
            fetchResponseButton.setEnabled(enabled);
            getCookieButton.setEnabled(enabled);
            updateCookiesButton.setEnabled(enabled);
            requestComboBox.setEnabled(enabled);
        } else {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    setEnabled(enabled);
                }
            });
        }
    }
    
    public ColumnDataModel[] getConversationColumns() {
        return null;
    }
    
    public ColumnDataModel[] getUrlColumns() {
        return null;
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JSplitPane conversationSplitPane;
    private javax.swing.JButton fetchResponseButton;
    private javax.swing.JButton getCookieButton;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JComboBox requestComboBox;
    private javax.swing.JButton updateCookiesButton;
    // End of variables declaration//GEN-END:variables
    
    private class RequestUpdater implements Runnable {
        
        private Request _req;
        
        public void setRequest(Request request) {
            _req = request;
            if (SwingUtilities.isEventDispatchThread()) {
                run();
            } else {
                try {
                    SwingUtilities.invokeAndWait(this);
                } catch (Exception e) {
                    _logger.info("Exception " + e);
                }
            }
        }
        
        public void run() {
            _requestPanel.setEditable(true);
            _requestPanel.setRequest(_req);
        }
        
    }
    
    private class ResponseUpdater implements Runnable {
        
        private Response _resp;
        
        public void setResponse(Response response) {
            _resp = response;
            if (SwingUtilities.isEventDispatchThread()) {
                run();
            } else {
                try {
                    SwingUtilities.invokeAndWait(this);
                } catch (Exception e) {
                    _logger.info("Exception " + e);
                }
            }
        }
        
        public void run() {
            _responsePanel.setEditable(false);
            _responsePanel.setResponse(_resp);
        }
        
    }
    
}
